import { SingletonBase } from "../../Framework/Managers/SingletonBase";

export class ListenerManager extends SingletonBase{
    //监听集合
    private m_ListenerMap=new Map<string,Map<any,Delegate[]>>();

    //#region 判断是否存在监听
    //是否有该类型的监听
    public has(type:string,caller:any,listener:Function):boolean{
        return this.find(type,caller,listener)!==null;
    }
    //查找一个监听 不存在时 创建监听
    private find(type:string,caller:any,listener:Function):Delegate{
        if(!type){
            console.error('type is null');
            return null;
        }
        if(!caller){
            console.error("caller is null");
            return null;
        }
        if(!listener){
            console.error("listtener is null");
            return null;
        }

        let listenerMap:Map<any,Delegate[]>;
        if(this.m_ListenerMap.has(type)){
            //有监听
            listenerMap=this.m_ListenerMap.get(type);
        }
        else{
            //没有该类型监听 创建监听
            listenerMap=new Map<any,Delegate[]>();
            this.m_ListenerMap.set(type,listenerMap);
        }
        let listenerList:Delegate[];
        if(listenerMap.has(caller)){
            listenerList=listenerMap.get(caller);
        }
        else{
            listenerList=[];
            listenerMap.set(caller,listenerList);
        }

        for(let delegate of listenerList){
            if(delegate.m_Listener===listener){
                return delegate;
            }
        }
        return null;
    }
    //#endregion

    //#region 触发监听
    //触发监听
    public trigger(type:string,...argArray:any[]):boolean{
        if(!type){
            console.error("type is null");
            return false;
        }
        let delegateList:Delegate[]=[];
        let callerList:any[]=[];
        let listenerMap=this.m_ListenerMap.get(type);
        if(listenerMap){
            listenerMap.forEach((listenerList,caller)=>{
                for(let delegate of listenerList){
                    delegateList.push(delegate);
                    callerList.push(caller);
                }
                for(let index=listenerList.length-1;index>=0;--index){
                    if(listenerList[index].isOnce){
                        listenerList.splice(index,1);
                    }
                }
                if(listenerList.length<=0){
                    listenerMap.delete(caller);
                }
            });
            if(listenerMap.size<=0){
                this.m_ListenerMap.delete(type);
            }
        }
        let len=delegateList.length;
        for(let index =0;index<len;index++){
            let delegate:Delegate=delegateList[index];
            delegate.listener.call(callerList[index],...delegate.argArray,...argArray);
        }
        return len>0;
    }
    //#endregion

    //#region 添加监听
    //添加监听
    public add(type:string,caller:any,listener:Function,...argArray:any[]):void{
        this.addListener(type,caller,listener,false,...argArray);
    }
    //添加一个只监听一次的监听
    public addOnce(type:string,caller:any,listener:Function,...argArray:any[]):void{
        this.addListener(type,caller,listener,true,...argArray);
    }
    private addListener(type:string,caller:any,listener:Function,isOnce:boolean,...argArray:any[]):void{
        let delegate=this.find(type,caller,listener);
        if(delegate){
            delegate.m_IsOnce=isOnce;
            console.error("listener is already exist");
        }
        else{
            let delegate=new Delegate(listener,argArray,isOnce);
            this.m_ListenerMap.get(type).get(caller).push(delegate);
        }
    }
    //#endregion

    //#region 移除监听
    //移除一个监听
    public remove(type:string,caller:any,listener:Function,onceOnly?:boolean):void{
        this.removeBy((listenerType,listenerCaller,delegate)=>{
            if(type&&type!==listenerType){
                return false;
            }
            if(caller&&caller!=listenerCaller){
                return false;
            }
            if(onceOnly&&!delegate.m_IsOnce){
                return false;
            }
            return true;
        });
    }
    private removeBy(predicate:(type:string,caller:any,delegate:Delegate)=>boolean):void{
        if(!predicate){
            return;
        }
        this.m_ListenerMap.forEach((listenerMap,type)=>{
            listenerMap.forEach((listenerList,caller)=>{
                for(let index=listenerList.length-1;index>=0;--index){
                    let delegate=listenerList[index];
                    if(predicate(type,caller,delegate)){
                        listenerList.splice(index,1);
                    }
                }
                if(listenerMap.size<=0){
                    this.m_ListenerMap.delete(type);
                }
            })
        });
    }

    //移除所有监听
    public removeAll(caller:any):void{
        this.m_ListenerMap.forEach((listenerMap,type)=>{
            listenerMap.delete(caller);
            if(listenerMap.size<=0){
                this.m_ListenerMap.delete(type);
            }
        });
    }
    //#endregion

}

//#region 事件委托
//事件委托
export class Delegate{
    //回调
    public m_Listener:Function;
    public get listener():Function{
        return this.m_Listener;
    }

    //参数
    public m_ArgArray:any[];
    public get argArray():any[]{
        return this.m_ArgArray;
    }

    //是否只监听一次
    public m_IsOnce=false;
    public get isOnce():boolean{
        return this.m_IsOnce;
    }

    //构造函数
    constructor(listener:Function,argArray:any[],isOnce:boolean=false){
        this.m_Listener=listener;
        this.m_ArgArray=argArray;
        this.m_IsOnce=isOnce;
    }
}
//#endregion
